#include "grass.h"

void cGrass::OnInit(string fxname,string texname)
{
	m_pDevice9 = GetDevice9();
	cShaderMgr* pShaderMgr = GetShaderMgr();
	cTextureMgr* pTextureMgr = GetTextureMgr();
	m_pEffect = pShaderMgr->GetShader(fxname);
	m_pTex = pTextureMgr->GetTex(texname);
	m_pTexAlpha = pTextureMgr->GetTex(texname+alpha);
}
void cGrass::Update(float dt)
{

}
void cGrass::Render()
{
	cCamera* pCamera = GetCamera();
	m_pDevice9->BeginScene();
	m_pEffect->SetTechnique("GrassTech");
	m_pEffect->SetTexture("gTex",m_pTex);
	m_pEffect->SetTexture("gTexAlpha",m_pTexAlpha);
	/*
	D3DXVECTOR3 axis = D3DXVECTOR3(0.707,0,0.707);
	D3DXMATRIX mat;
	D3DXMatrixRotationAxis(&mat,&axis,D3DX_PI/4);
	*/
	HR( m_pEffect->SetMatrix("gWVP",&GetViewProj() ) );

	UINT passes = 0;
	m_pEffect->Begin(&passes,0);
	for(int i = 0;i!=passes;++i)
	{
		m_pEffect->BeginPass(i);
		m_pMesh->DrawSubset(0);
		m_pEffect->EndPass();
	}
	m_pEffect->End();
	m_pDevice9->EndScene();
}
void cGrass::Release()
{
	SAFE_RELEASE(m_pMesh);
}
void cGrass::SetGrassGrid(DWORD dwNum,vector<D3DXVECTOR3>& vecGrassPos,float radius,float grasswidth,float grassheight)
{
	m_GrassHeight = grassheight;	
	m_GrassWidth = grasswidth;
	RandomizePos(vecGrassPos,dwNum);
	CreateGrassGeometry(m_pDevice9,vecGrassPos,dwNum,m_GrassHeight,m_GrassWidth,radius,&m_pMesh);
	//CreatePlaneGrass(m_pDevice9,vecGrassPos,dwNum,m_GrassHeight,m_GrassWidth,&m_pMesh);
}
void cGrass::SetTexture(string tex)
{
	cTextureMgr* pTextureMgr = GetTextureMgr();
	m_pTex = pTextureMgr->GetTex(tex);
}

//////////////////////////////////////////////////////////////////////////
void CreateGrassGeometry(LPDIRECT3DDEVICE9 pDevice9,vector<D3DXVECTOR3>& vecPos,DWORD dwNum,
	float inGrassHeight,float inGrassWidth,float inRadius,ID3DXMesh** outMesh)
{
	srand(unsigned(time(0)));
	float bias = inRadius*0.5f;

	vector<D3DXVECTOR3> vecVertex;
	vector<DWORD> vecIndex;
	vecVertex.resize(dwNum*12);
	vecIndex.resize(dwNum*18);
	for(int i = 0;i!=dwNum;++i)
	{
		float x = vecPos[i].x - 75 + rand()%75;
		float z = vecPos[i].z - 75 + rand()%75;
		D3DXVECTOR3 center = D3DXVECTOR3(x,inGrassHeight,z);
		float theta = 0.0f;
		float sintheta = 0.0f;
		float costheta = 0.0f;
		for(int j = 0;j!=3;++j)
		{
			costheta = cos(theta);
			sintheta = sin(theta);
			x = -inGrassWidth*0.5;
			z = 0;
			vecVertex[i*NumGrassVertex+j*4] = D3DXVECTOR3(x*costheta-z*sintheta,0.0f,z*costheta+x*sintheta);
			vecVertex[i*NumGrassVertex+j*4] += GrassBias[j]*bias;
			vecVertex[i*NumGrassVertex+j*4] += center;
			vecVertex[i*NumGrassVertex+j*4+2] = D3DXVECTOR3(x*costheta-z*sintheta,-inGrassHeight,z*costheta+x*sintheta);
			vecVertex[i*NumGrassVertex+j*4+2] += GrassBias[j]*bias;
			vecVertex[i*NumGrassVertex+j*4+2] += center;

			x = inGrassWidth*0.5;
			z = 0;
			vecVertex[i*NumGrassVertex+j*4+1] = D3DXVECTOR3(x*costheta-z*sintheta,0.0f,z*costheta+x*sintheta);
			vecVertex[i*NumGrassVertex+j*4+1] += GrassBias[j]*bias;
			vecVertex[i*NumGrassVertex+j*4+1] += center;
			vecVertex[i*NumGrassVertex+j*4+3] = D3DXVECTOR3(x*costheta-z*sintheta,-inGrassHeight,z*costheta+x*sintheta); 
			vecVertex[i*NumGrassVertex+j*4+3] += GrassBias[j]*bias;
			vecVertex[i*NumGrassVertex+j*4+3] += center;
			theta+=D3DX_PI/3;
		}
	}
	for(int i = 0;i!=dwNum;++i)
	{
		int baseIndex = i*12;
		for(int j = 0;j!=3;++j)
		{
			vecIndex[i*18+j*6]   = baseIndex+0;
			vecIndex[i*18+j*6+1] = baseIndex+1;
			vecIndex[i*18+j*6+2] = baseIndex+2;

			vecIndex[i*18+j*6+3] = baseIndex+2;
			vecIndex[i*18+j*6+4] = baseIndex+1;
			vecIndex[i*18+j*6+5] = baseIndex+3;
			baseIndex+=4;
		}
	}
	ID3DXMesh* pMesh;
	HR(D3DXCreateMeshFVF(dwNum*6,dwNum*12,D3DXMESH_32BIT|D3DXMESH_MANAGED,SimpleFVF,pDevice9,&pMesh));
	SimpleVertex* pVertex;
	HR(pMesh->LockVertexBuffer(0,(void**)&pVertex));
	for(int i = 0;i!=dwNum*3;++i)
	{
		pVertex[i*4].pos = vecVertex[i*4];
		pVertex[i*4].tex = D3DXVECTOR2(0.0f,0.0f);
		pVertex[i*4+1].pos = vecVertex[i*4+1];
		pVertex[i*4+1].tex = D3DXVECTOR2(1.0f,0.0f);
		pVertex[i*4+2].pos = vecVertex[i*4+2];
		pVertex[i*4+2].tex = D3DXVECTOR2(0.0f,1.0f);
		pVertex[i*4+3].pos = vecVertex[i*4+3];
		pVertex[i*4+3].tex = D3DXVECTOR2(1.0f,1.0f);
	}
	HR(pMesh->UnlockVertexBuffer());

	DWORD* pIndex;
	DWORD* pAttr;
	HR(pMesh->LockIndexBuffer(0,(void**)&pIndex));
	HR(pMesh->LockAttributeBuffer(0,&pAttr));
	for(int i = 0;i!=vecIndex.size();++i)
	{
		pIndex[i] = vecIndex[i];
	}
	for(int i = 0;i!=dwNum*6;++i)
	{
		pAttr[i] = 0;
	}
	HR(pMesh->UnlockIndexBuffer());
	HR(pMesh->UnlockAttributeBuffer());

	DWORD* ajancency = new DWORD[pMesh->GetNumFaces()*3];
	pMesh->GenerateAdjacency(0.01f,ajancency);
	pMesh->OptimizeInplace(D3DXMESH_MANAGED|D3DXMESHOPT_ATTRSORT,ajancency,NULL,NULL,NULL);
	delete [] ajancency;

	*outMesh = pMesh;
}

void CreatePlaneGrass(LPDIRECT3DDEVICE9 pDevice9,vector<D3DXVECTOR3>& vecGrassPos,DWORD dwNum,
	float inGrassHeight,float inGrassWidth,ID3DXMesh** outMesh)
{
	int grassVertex = 4;
	int grassIndex	= 6;
	float xPos,zPos;

	ID3DXMesh* pMesh;
	HR(D3DXCreateMeshFVF(dwNum*2,grassVertex*dwNum,D3DXMESH_MANAGED|D3DXMESH_32BIT,SimpleFVF,pDevice9,&pMesh));
	SimpleVertex* pVertex = NULL;
	HR(pMesh->LockVertexBuffer(0,(void**)&pVertex));
	D3DXVECTOR3 axis = D3DXVECTOR3(0.707,0,0.707);
	for(int i = 0;i!=dwNum;++i)
	{
		xPos = vecGrassPos[i].x - 75 + rand()%150;
		zPos = vecGrassPos[i].z - 75 + rand()%150;

		pVertex[grassVertex*i].pos = D3DXVECTOR3(xPos,inGrassHeight,zPos)-inGrassWidth/2*axis;
		pVertex[grassVertex*i].tex = D3DXVECTOR2(0,0);

		pVertex[grassVertex*i+1].pos = D3DXVECTOR3(xPos,inGrassHeight,zPos)+inGrassWidth/2*axis;
		pVertex[grassVertex*i+1].tex = D3DXVECTOR2(1,0);

		pVertex[grassVertex*i+2].pos = D3DXVECTOR3(xPos,0,zPos)-inGrassWidth/2*axis;
		pVertex[grassVertex*i+2].tex = D3DXVECTOR2(0,1);

		pVertex[grassVertex*i+3].pos = D3DXVECTOR3(xPos,0,zPos)+inGrassWidth/2*axis;
		pVertex[grassVertex*i+3].tex = D3DXVECTOR2(1,1);
	}
	HR(pMesh->UnlockVertexBuffer());

	DWORD* pIndex = NULL;
	DWORD* pAttribute = NULL;
	HR(pMesh->LockIndexBuffer(0,(void**)&pIndex));
	HR(pMesh->LockAttributeBuffer(0,&pAttribute));
	for(int i = 0;i!=dwNum;++i)
	{
		pIndex[grassIndex*i] = grassVertex*i + 0;
		pIndex[grassIndex*i+1] = grassVertex*i + 1;
		pIndex[grassIndex*i+2] = grassVertex*i + 2;

		pIndex[grassIndex*i+3] = grassVertex*i + 2;
		pIndex[grassIndex*i+4] = grassVertex*i + 1;
		pIndex[grassIndex*i+5] = grassVertex*i + 3;
	}
	for(int i = 0;i!=dwNum*2;++i)
	{
		pAttribute[i] = 0;
	}
	HR(pMesh->UnlockIndexBuffer());
	HR(pMesh->UnlockAttributeBuffer());


	DWORD* ajancency = new DWORD[pMesh->GetNumFaces()*3];
	pMesh->GenerateAdjacency(0.01f,ajancency);
	pMesh->OptimizeInplace(D3DXMESH_MANAGED|D3DXMESHOPT_ATTRSORT,ajancency,NULL,NULL,NULL);
	delete [] ajancency;

	*outMesh = pMesh;
}